#ifndef GIGECAM_H
#define GIGECAM_H

#include <QObject>
#include <QSize>
#include <QStringList>
#include <QImage>
#include "tisudshl.h"
#include "SimplePropertyAccess.h"
#include <algorithm>
using namespace DShowLib;

class TisCameraListener;
class TisCamera;

class DShowLibAutoInit
{
public:
    DShowLibAutoInit();
    ~DShowLibAutoInit();
    static DShowLib::Grabber * grabber() {return m_pGrabber;}
    static bool state() {return m_libState;}
private:
    static DShowLib::Grabber * m_pGrabber;
    static bool m_libState;
};

class TisCameraInfo
{
    friend class TisCamera;
public:
    explicit TisCameraInfo(const QByteArray &name = QByteArray());
    explicit TisCameraInfo(const TisCamera &camera);
    TisCameraInfo(const TisCameraInfo &other);
    explicit TisCameraInfo(const VideoCaptureDeviceItem &item);
    QString description() const;
    QString deviceName() const;
    bool isNull() const;
    int orientation() const;
    bool operator!=(const TisCameraInfo &other) const;
    TisCameraInfo & operator=(const TisCameraInfo &other);
    bool operator==(const TisCameraInfo &other) const;

    static QList<TisCameraInfo> availableCameras();
    static TisCameraInfo defaultCamera();

    ~TisCameraInfo(){}

    /// 下面这些是 TIS 相机独有的，QCameraInfo 没有这些功能
    __int64 deviceSerialNumber() const;
    bool driverVersion( int& major, int& minor, int& spnum, int& build );


private:
    VideoCaptureDeviceItem m_TisCameraIterm;
};


class TisCamera : public QObject
{
    friend class TisCameraInfo;
    Q_OBJECT
public:
    explicit TisCamera(QObject *parent = 0);
    ~TisCamera();
    bool initFrameHandlerSink();
    bool selectDevice();

    bool openDevice(const TisCameraInfo &info);
    bool loadDeviceStateFromFile(const std::string& filename, bool bOpenDev = true);
    bool saveDeviceStateToFile( const std::string& filename);

    bool setVideoFormat(QString format);

    QStringList listVideoFormats();
    QStringList listVideoNorms();


    bool isValid();
    bool isLive();
    void initFrameRate();
    void initVCDPropertyAccess();

    double frameRate();
    int expoureTime();

public slots:
    /**
    * @brief 开始采集图像
    * @param show  true 表示打开一个新的窗口显示视频， false 则不打开新的窗口
    * @return true 表示图像采集正常，false 表示图像采集失败
    */
    bool startLive(bool show = true);
    bool stopLive();
    bool suspendLive();
    void closeDevice();
    bool showVCDPropertyPage( );
    bool autoBrightness(bool on);
    bool autoWhiteBalance(bool on);
    bool onePush();
private:
    //static int m_DShowlibInitCounter;
    DShowLib::Grabber* m_pGrabber;
    Grabber::tVidCapDevListPtr m_pVidCapDevList;

    TisCameraListener *m_pListener;
    DShowLib::FrameTypeInfoArray m_acceptedTypes;
    smart_ptr<FrameHandlerSink> m_pFrameHandlerSink;
    CSimplePropertyAccess m_VCDProp;

    // 相机支持的帧速率，及当前的帧速率
    Grabber::tFPSListPtr  m_pFrameRateList;
    double m_framerate;

    float m_exposureTime;
    float m_minExposureTime;
    float m_maxExposureTime;

    bool m_autoBrightness;
    bool m_autoWhiteBalance;
signals:
    void Mono8ImageChanged(const uint8_t *pBuf, QSize size);
    void RGB24ImageChanged(const uint8_t *pBuf, QSize size);
    void RGB32ImageChanged(const uint8_t *pBuf, QSize size);
    void imageChanged(QImage& image);
    void deviceLost();
public slots:
    void setFrameRate(double fps);
    void setBrightness(int value);
    void setWhiteBalance(int red, int blue);
    bool setExpoureTime(int value);
};

class TisCameraListener : public DShowLib::GrabberListener
{
public:
    explicit TisCameraListener(TisCamera *pCamera, SIZE size);
    //explicit CameraListener(GigECam *pCamera);
    ~TisCameraListener();
    TisCamera * m_pCamera;
    //QImage m_image;

public:
    // Overwrite the GrabberListener methods we need
    void frameReady( DShowLib::Grabber& caller, smart_ptr<DShowLib::MemBuffer> pBuffer, DWORD FrameNumber );
    void deviceLost( Grabber& caller );
};
#endif // GIGECAM_H
